package com.lifeonwalden.copula;

import org.apache.commons.math3.stat.correlation.KendallsCorrelation;
import org.apache.commons.math3.stat.correlation.PearsonsCorrelation;
import org.apache.commons.math3.stat.correlation.SpearmansCorrelation;

import java.math.BigDecimal;

public abstract class Copula {
    public static BigDecimal calcKendall(double[] a, double[] b) {
        return BigDecimal.valueOf(new KendallsCorrelation().correlation(a, b));
    }

    public static BigDecimal calcPearson(double[] a, double[] b) {
        return BigDecimal.valueOf(new PearsonsCorrelation().correlation(a, b));
    }

    public static BigDecimal calcSpearman(double[] a, double[] b) {
        return BigDecimal.valueOf(new SpearmansCorrelation().correlation(a, b));
    }

    /**
     * Returns the cumulative distribution function (CDF) of the copula.
     *
     * @param data
     * @return
     */
    public abstract BigDecimal cdf(double[] data);

    /**
     * Returns the probability distribution function (PDF) of the copula.
     *
     * @param data
     * @return
     */
    public abstract BigDecimal pdf(double[] data);

    /**
     * Returns the theoritical lower concentration function.
     *
     * @param x
     * @return
     */
    public abstract BigDecimal concentrationDown(double x);

    /**
     * Returns the theoritical upper concentration function.
     *
     * @param x
     * @return
     */
    public abstract BigDecimal concentrationUp(double x);

    /**
     * Returns the theoritical concentration function.
     *
     * @param x
     * @return
     */
    public BigDecimal concentrationFunction(double x) {
        if (x < 0 || x > 1) {
            throw new RuntimeException("The argument must be included between 0 and 1.");
        } else if (x < 0.5) {
            return this.concentrationDown(x);
        } else {
            return this.concentrationUp(x);
        }
    }
}
